from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox,
                             QPushButton, QTextEdit, QProgressBar, QLabel,
                             QTableWidget, QTableWidgetItem, QHeaderView,
                             QTabWidget, QSplitter, QCheckBox, QSpinBox,
                             QComboBox, QFormLayout)
from PyQt6.QtCore import Qt, pyqtSignal, QTimer
from PyQt6.QtGui import QFont, QColor
from typing import Dict, Any, List, Optional
from loguru import logger
from datetime import datetime


class ExecutionWidget(QWidget):
    """脚本执行结果组件"""
    
    # 信号定义
    run_script = pyqtSignal()      # 运行脚本信号
    stop_execution = pyqtSignal()  # 停止执行信号
    
    def __init__(self):
        super().__init__()
        self.is_executing = False
        self.execution_results: List[Dict[str, Any]] = []
        self.current_result: Optional[Dict[str, Any]] = None
        
        self.init_ui()
        self.setup_connections()
    
    def init_ui(self):
        """初始化界面"""
        layout = QVBoxLayout(self)
        
        # 执行控制区域
        control_group = QGroupBox("执行控制")
        control_layout = QVBoxLayout(control_group)
        
        # 执行配置
        config_layout = QFormLayout()
        
        # 超时设置
        self.timeout_spinbox = QSpinBox()
        self.timeout_spinbox.setRange(10, 600)
        self.timeout_spinbox.setValue(60)
        self.timeout_spinbox.setSuffix(" 秒")
        config_layout.addRow("执行超时:", self.timeout_spinbox)
        
        # 重试设置
        self.retry_checkbox = QCheckBox("失败重试")
        self.retry_count_spinbox = QSpinBox()
        self.retry_count_spinbox.setRange(1, 5)
        self.retry_count_spinbox.setValue(1)
        self.retry_count_spinbox.setEnabled(False)
        
        retry_layout = QHBoxLayout()
        retry_layout.addWidget(self.retry_checkbox)
        retry_layout.addWidget(QLabel("重试次数:"))
        retry_layout.addWidget(self.retry_count_spinbox)
        retry_layout.addStretch()
        
        config_layout.addRow("重试配置:", retry_layout)
        
        # 环境选择
        self.env_combo = QComboBox()
        self.env_combo.addItems(["开发环境", "测试环境", "生产环境"])
        config_layout.addRow("执行环境:", self.env_combo)
        
        control_layout.addLayout(config_layout)
        
        # 控制按钮
        button_layout = QHBoxLayout()
        
        self.run_btn = QPushButton("运行脚本")
        self.run_btn.setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; }")
        
        self.stop_btn = QPushButton("停止执行")
        self.stop_btn.setStyleSheet("QPushButton { background-color: #f44336; color: white; font-weight: bold; }")
        self.stop_btn.setEnabled(False)
        
        self.clear_btn = QPushButton("清空结果")
        
        button_layout.addWidget(self.run_btn)
        button_layout.addWidget(self.stop_btn)
        button_layout.addWidget(self.clear_btn)
        button_layout.addStretch()
        
        control_layout.addLayout(button_layout)
        
        # 执行状态
        status_layout = QHBoxLayout()
        
        self.status_label = QLabel("就绪")
        self.status_label.setStyleSheet("QLabel { color: #666; }")
        
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        
        self.duration_label = QLabel("00:00")
        self.duration_label.setFont(QFont("monospace", 12))
        
        status_layout.addWidget(QLabel("状态:"))
        status_layout.addWidget(self.status_label)
        status_layout.addWidget(self.progress_bar)
        status_layout.addWidget(QLabel("耗时:"))
        status_layout.addWidget(self.duration_label)
        status_layout.addStretch()
        
        control_layout.addLayout(status_layout)
        
        layout.addWidget(control_group)
        
        # 执行结果区域
        results_splitter = QSplitter(Qt.Orientation.Vertical)
        
        # 当前执行结果
        current_group = QGroupBox("当前执行结果")
        current_layout = QVBoxLayout(current_group)
        
        # 结果标签页
        self.result_tabs = QTabWidget()
        
        # 输出标签页
        self.output_text = QTextEdit()
        self.output_text.setFont(QFont("Consolas", 10))
        self.output_text.setReadOnly(True)
        self.result_tabs.addTab(self.output_text, "执行输出")
        
        # 错误标签页
        self.error_text = QTextEdit()
        self.error_text.setFont(QFont("Consolas", 10))
        self.error_text.setReadOnly(True)
        self.error_text.setStyleSheet("QTextEdit { color: red; }")
        self.result_tabs.addTab(self.error_text, "错误信息")
        
        # 详细信息标签页
        self.details_text = QTextEdit()
        self.details_text.setFont(QFont("Consolas", 10))
        self.details_text.setReadOnly(True)
        self.result_tabs.addTab(self.details_text, "详细信息")
        
        current_layout.addWidget(self.result_tabs)
        
        results_splitter.addWidget(current_group)
        
        # 历史执行记录
        history_group = QGroupBox("执行历史")
        history_layout = QVBoxLayout(history_group)
        
        self.history_table = QTableWidget()
        self.history_table.setColumnCount(6)
        self.history_table.setHorizontalHeaderLabels([
            "执行时间", "脚本名称", "状态", "耗时", "成功率", "备注"
        ])
        
        # 设置表格属性
        header = self.history_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)  # 执行时间
        header.setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)           # 脚本名称
        header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)  # 状态
        header.setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)  # 耗时
        header.setSectionResizeMode(4, QHeaderView.ResizeMode.ResizeToContents)  # 成功率
        header.setSectionResizeMode(5, QHeaderView.ResizeMode.Stretch)           # 备注
        
        self.history_table.setAlternatingRowColors(True)
        self.history_table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        
        history_layout.addWidget(self.history_table)
        
        # 历史记录操作按钮
        history_buttons_layout = QHBoxLayout()
        
        self.export_history_btn = QPushButton("导出历史")
        self.clear_history_btn = QPushButton("清空历史")
        self.refresh_history_btn = QPushButton("刷新")
        
        history_buttons_layout.addWidget(self.export_history_btn)
        history_buttons_layout.addWidget(self.clear_history_btn)
        history_buttons_layout.addWidget(self.refresh_history_btn)
        history_buttons_layout.addStretch()
        
        history_layout.addLayout(history_buttons_layout)
        
        results_splitter.addWidget(history_group)
        
        # 设置分割器比例
        results_splitter.setSizes([400, 200])
        
        layout.addWidget(results_splitter)
    
    def setup_connections(self):
        """设置信号连接"""
        # 控制按钮
        self.run_btn.clicked.connect(self.on_run_script)
        self.stop_btn.clicked.connect(self.on_stop_execution)
        self.clear_btn.clicked.connect(self.clear_current_result)
        
        # 重试复选框
        self.retry_checkbox.toggled.connect(self.retry_count_spinbox.setEnabled)
        
        # 历史记录操作
        self.export_history_btn.clicked.connect(self.export_history)
        self.clear_history_btn.clicked.connect(self.clear_history)
        self.refresh_history_btn.clicked.connect(self.refresh_history)
        
        # 历史记录选择
        self.history_table.itemSelectionChanged.connect(self.on_history_selection_changed)
    
    def on_run_script(self):
        """运行脚本按钮点击"""
        if not self.is_executing:
            self.start_execution()
            self.run_script.emit()
    
    def on_stop_execution(self):
        """停止执行按钮点击"""
        if self.is_executing:
            self.stop_execution.emit()
            self.finish_execution({"success": False, "error": "用户中断执行", "duration": 0})
    
    def start_execution(self):
        """开始执行"""
        self.is_executing = True
        
        # 更新界面状态
        self.run_btn.setEnabled(False)
        self.stop_btn.setEnabled(True)
        self.status_label.setText("执行中...")
        self.status_label.setStyleSheet("QLabel { color: #FF9800; font-weight: bold; }")
        
        # 显示进度条
        self.progress_bar.setVisible(True)
        self.progress_bar.setRange(0, 0)  # 不确定进度
        
        # 清空当前结果
        self.clear_current_result()
        
        # 开始计时
        self.execution_start_time = datetime.now()
        self.duration_timer = QTimer()
        self.duration_timer.timeout.connect(self.update_duration)
        self.duration_timer.start(1000)
        
        logger.info("开始执行脚本")
    
    def finish_execution(self, result: Dict[str, Any]):
        """完成执行"""
        self.is_executing = False
        
        # 停止计时器
        if hasattr(self, 'duration_timer'):
            self.duration_timer.stop()
        
        # 更新界面状态
        self.run_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)
        self.progress_bar.setVisible(False)
        
        # 更新状态
        if result.get("success", False):
            self.status_label.setText("执行成功")
            self.status_label.setStyleSheet("QLabel { color: #4CAF50; font-weight: bold; }")
        else:
            self.status_label.setText("执行失败")
            self.status_label.setStyleSheet("QLabel { color: #f44336; font-weight: bold; }")
        
        # 显示结果
        self.show_result(result)
        
        # 添加到历史记录
        self.add_to_history(result)
        
        logger.info(f"脚本执行完成，成功: {result.get('success', False)}")
    
    def show_result(self, result: Dict[str, Any]):
        """显示执行结果"""
        self.current_result = result
        
        # 显示输出
        output = result.get("output", "")
        self.output_text.setPlainText(output)
        
        # 显示错误
        error = result.get("error", "")
        self.error_text.setPlainText(error)
        
        # 显示详细信息
        details = self.format_result_details(result)
        self.details_text.setPlainText(details)
        
        # 根据结果切换标签页
        if error:
            self.result_tabs.setCurrentWidget(self.error_text)
        else:
            self.result_tabs.setCurrentWidget(self.output_text)
    
    def format_result_details(self, result: Dict[str, Any]) -> str:
        """格式化结果详细信息"""
        details = []
        
        details.append(f"执行状态: {'成功' if result.get('success', False) else '失败'}")
        details.append(f"执行时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        details.append(f"执行耗时: {result.get('duration', 0):.2f} 秒")
        
        if result.get("timeout"):
            details.append(f"超时设置: {self.timeout_spinbox.value()} 秒")
        
        if result.get("retry_count"):
            details.append(f"重试次数: {result.get('retry_count', 0)}")
        
        details.append(f"执行环境: {self.env_combo.currentText()}")
        
        # 添加错误详情
        if result.get("error"):
            details.append("")
            details.append("错误详情:")
            details.append("-" * 40)
            details.append(result["error"])
        
        # 添加输出详情
        if result.get("output"):
            details.append("")
            details.append("输出详情:")
            details.append("-" * 40)
            details.append(result["output"])
        
        return "\n".join(details)
    
    def clear_current_result(self):
        """清空当前结果"""
        self.current_result = None
        self.output_text.clear()
        self.error_text.clear()
        self.details_text.clear()
        self.duration_label.setText("00:00")
    
    def update_duration(self):
        """更新执行时长"""
        if hasattr(self, 'execution_start_time'):
            duration = datetime.now() - self.execution_start_time
            total_seconds = int(duration.total_seconds())
            minutes = total_seconds // 60
            seconds = total_seconds % 60
            self.duration_label.setText(f"{minutes:02d}:{seconds:02d}")
    
    def add_to_history(self, result: Dict[str, Any]):
        """添加到历史记录"""
        try:
            # 创建历史记录条目
            history_item = {
                "timestamp": datetime.now(),
                "script_name": result.get("script_name", "未知脚本"),
                "success": result.get("success", False),
                "duration": result.get("duration", 0),
                "error": result.get("error", ""),
                "output": result.get("output", ""),
                "environment": self.env_combo.currentText(),
                "timeout": self.timeout_spinbox.value(),
                "retry_enabled": self.retry_checkbox.isChecked(),
                "retry_count": self.retry_count_spinbox.value() if self.retry_checkbox.isChecked() else 0
            }
            
            self.execution_results.append(history_item)
            
            # 更新历史记录表格
            self.refresh_history()
            
        except Exception as e:
            logger.error(f"添加历史记录失败: {e}")
    
    def refresh_history(self):
        """刷新历史记录"""
        try:
            self.history_table.setRowCount(len(self.execution_results))
            
            for row, item in enumerate(self.execution_results):
                # 执行时间
                time_item = QTableWidgetItem(item["timestamp"].strftime("%Y-%m-%d %H:%M:%S"))
                self.history_table.setItem(row, 0, time_item)
                
                # 脚本名称
                name_item = QTableWidgetItem(item["script_name"])
                self.history_table.setItem(row, 1, name_item)
                
                # 状态
                status_item = QTableWidgetItem("成功" if item["success"] else "失败")
                if item["success"]:
                    status_item.setBackground(QColor(200, 255, 200))
                else:
                    status_item.setBackground(QColor(255, 200, 200))
                self.history_table.setItem(row, 2, status_item)
                
                # 耗时
                duration_item = QTableWidgetItem(f"{item['duration']:.2f}s")
                self.history_table.setItem(row, 3, duration_item)
                
                # 成功率（基于历史记录计算）
                success_rate = self.calculate_success_rate(item["script_name"])
                rate_item = QTableWidgetItem(f"{success_rate:.1%}")
                self.history_table.setItem(row, 4, rate_item)
                
                # 备注
                remark = item["error"][:50] + "..." if len(item["error"]) > 50 else item["error"]
                remark_item = QTableWidgetItem(remark if not item["success"] else "执行成功")
                self.history_table.setItem(row, 5, remark_item)
            
            # 按时间倒序排列
            self.history_table.sortItems(0, Qt.SortOrder.DescendingOrder)
            
        except Exception as e:
            logger.error(f"刷新历史记录失败: {e}")
    
    def calculate_success_rate(self, script_name: str) -> float:
        """计算脚本成功率"""
        script_results = [r for r in self.execution_results if r["script_name"] == script_name]
        if not script_results:
            return 0.0
        
        success_count = sum(1 for r in script_results if r["success"])
        return success_count / len(script_results)
    
    def on_history_selection_changed(self):
        """历史记录选择改变"""
        current_row = self.history_table.currentRow()
        if current_row >= 0 and current_row < len(self.execution_results):
            # 显示选中的历史记录详情
            selected_result = self.execution_results[current_row]
            
            # 转换为结果格式
            result = {
                "success": selected_result["success"],
                "output": selected_result["output"],
                "error": selected_result["error"],
                "duration": selected_result["duration"],
                "script_name": selected_result["script_name"]
            }
            
            self.show_result(result)
    
    def export_history(self):
        """导出历史记录"""
        if not self.execution_results:
            from PyQt6.QtWidgets import QMessageBox
            QMessageBox.information(self, "提示", "没有可导出的历史记录")
            return
        
        try:
            from PyQt6.QtWidgets import QFileDialog
            file_path, _ = QFileDialog.getSaveFileName(
                self, "导出执行历史", "execution_history.json", "JSON文件 (*.json);;CSV文件 (*.csv)"
            )
            
            if file_path:
                if file_path.endswith('.csv'):
                    self.export_history_csv(file_path)
                else:
                    self.export_history_json(file_path)
                
                from PyQt6.QtWidgets import QMessageBox
                QMessageBox.information(self, "成功", f"历史记录已导出到: {file_path}")
                
        except Exception as e:
            from PyQt6.QtWidgets import QMessageBox
            QMessageBox.critical(self, "错误", f"导出失败: {str(e)}")
    
    def export_history_json(self, file_path: str):
        """导出为JSON格式"""
        import json
        
        # 转换为可序列化的格式
        export_data = []
        for item in self.execution_results:
            export_item = item.copy()
            export_item["timestamp"] = item["timestamp"].isoformat()
            export_data.append(export_item)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(export_data, f, ensure_ascii=False, indent=2)
    
    def export_history_csv(self, file_path: str):
        """导出为CSV格式"""
        import csv
        
        with open(file_path, 'w', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            
            # 写入表头
            writer.writerow([
                "执行时间", "脚本名称", "状态", "耗时(秒)", "环境",
                "超时设置", "重试", "错误信息", "输出"
            ])
            
            # 写入数据
            for item in self.execution_results:
                writer.writerow([
                    item["timestamp"].strftime("%Y-%m-%d %H:%M:%S"),
                    item["script_name"],
                    "成功" if item["success"] else "失败",
                    f"{item['duration']:.2f}",
                    item["environment"],
                    item["timeout"],
                    "是" if item["retry_enabled"] else "否",
                    item["error"],
                    item["output"]
                ])
    
    def clear_history(self):
        """清空历史记录"""
        from PyQt6.QtWidgets import QMessageBox
        
        reply = QMessageBox.question(
            self, "确认清空", "确定要清空所有执行历史吗？此操作不可撤销。",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            self.execution_results.clear()
            self.history_table.setRowCount(0)
            self.clear_current_result()
    
    def get_execution_config(self) -> Dict[str, Any]:
        """获取执行配置"""
        return {
            "timeout": self.timeout_spinbox.value(),
            "retry_enabled": self.retry_checkbox.isChecked(),
            "retry_count": self.retry_count_spinbox.value(),
            "environment": self.env_combo.currentText()
        }